package cc.tuhaolicai.mt.user.mobile.controller;

import com.google.common.collect.Lists;
import com.jfinal.core.Controller;
import com.jfinal.kit.Prop;
import com.jfinal.kit.PropKit;
import com.jfinal.render.JsonRender;
import eu.bitwalker.useragentutils.Browser;
import eu.bitwalker.useragentutils.UserAgent;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import pro.tools.data.text.ToolJson;
import pro.tools.time.DatePlus;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.lang.reflect.Field;
import java.util.*;

/**
 * @version V1.0
 * @Title： ExtController
 * @Package： cc.tuhaolicai.mt.predefined
 * @Description： 对 Jfinal Controller的扩展公共方法
 * @author： nan
 * @date： 2017-07-13 14:54
 */
public class ExtController extends Controller {

    private static final Logger logger = LoggerFactory.getLogger(ExtController.class);

    /**
     * @return 浏览器版本
     */
    private Browser getBrowser() {
        return new UserAgent(getRequest().getHeader("User-Agent")).getBrowser();
    }

    /**
     * @return 判断是否是IE
     */
    protected boolean isIE() {
        return getRequest().getHeader("User-Agent").toLowerCase().indexOf("msie") > 0 || getRequest().getHeader("User-Agent").toLowerCase().indexOf("rv:11.0") > 0 || getRequest().getHeader("User-Agent").toLowerCase().indexOf("edge") > 0;
    }

    /**
     * 重写renderJson，避免出现IE8下出现下载弹出框
     */
    @Override
    public void renderJson(Object object) {
        Browser browser = getBrowser();
        if (Browser.IE5.equals(browser) || Browser.IE6.equals(browser)
                || Browser.IE7.equals(browser) || Browser.IE8.equals(browser)) {
            render(new JsonRender(object).forIE());
        } else {
            super.renderJson(object);
        }
    }

    /**
     * 解决IE8下下载失败的问题
     */
    @Override
    public void renderFile(String file) {
        Browser browser = getBrowser();
        if (Browser.IE5.equals(browser) || Browser.IE6.equals(browser)
                || Browser.IE7.equals(browser) || Browser.IE8.equals(browser)) {
            getResponse().reset();
        }
        super.renderFile(file);
    }

    /**
     * 解决IE8下下载失败的问题
     */
    @Override
    public void renderFile(File file) {
        Browser browser = getBrowser();
        if (Browser.IE5.equals(browser) || Browser.IE6.equals(browser)
                || Browser.IE7.equals(browser) || Browser.IE8.equals(browser)) {
            getResponse().reset();
        }
        super.renderFile(file);
    }

    /**
     * 处理批量操作的的方法
     *
     * @param name 需要接收的属性名
     * @return 返回List类型
     */
    protected List<String> getParaList(String name) {
        String[] elements = getParaMap().get(name);
        if (elements != null && elements.length > 0) {
            return Lists.newArrayList(elements);
        } else {
            return Lists.newArrayList();
        }
    }


    /**
     * 把Map中value为数组的参数转换成普通的map的value参数
     *
     * @param request http请求
     * @return 返回转换完成后的普通map
     */
    protected Map<String, Object> mapParamToObj(HttpServletRequest request) {

        Map<String, String[]> convertMap = request.getParameterMap();
        Map<String, Object> newMap = new TreeMap<>();
        convertMap.forEach((key, value) -> newMap.put(key, value[0]));

        return newMap;
    }

    /**
     * 生成订单号
     * @param length 生成的订单号长度
     * @return 订单号
     */
    public static String getCodeStr(int length) {
        try {
            if (length <= 0) {
                return "";
            } else {
                Random r = new Random();
                StringBuffer result = new StringBuffer();

                for(int i = 0; i < length; ++i) {
                    result.append(Integer.toString(r.nextInt(10)));
                }

                return result.toString();
            }
        } catch (Exception var4) {
            logger.error(var4.getMessage());
            return "";
        }
    }

    /**
     * 把Map中value为数组的参数转换成普通的map的value参数
     *
     * @param request http请求
     * @return 返回转换完成后的普通map
     */
    protected <T> T mapParamToObj(HttpServletRequest request, Class<T> convertClass) {

        Map<String, String[]> convertMap = request.getParameterMap();
        Map<String, Object> newMap = new TreeMap<>();
        convertMap.forEach((key, value) -> newMap.put(key, value[0]));
        return ToolJson.mapToModel(newMap,convertClass);
    }

    /**
     * 把Map中value为数组的参数转换成普通的map的value参数
     *
     * @param request http请求
     * @return 返回转换完成后的普通map
     */
    protected Map<String, String> mapParamToStr(HttpServletRequest request) {

        Map<String, String[]> convertMap = request.getParameterMap();
        Map<String, String> newMap = new TreeMap<>();
        convertMap.forEach((key, value) -> newMap.put(key, value[0]));
        return newMap;
    }

    /**
     * 拼接数据
     *
     * @param objects   拼接的对象
     * @param separator 字符队列
     * @return 结果
     */
    public static String listToString(Object[] objects, char separator) {

        return StringUtils.join(objects, separator);
    }

    /**
     * 订单号和流水号生成策略
     *
     * @param userId          用户的主键
     * @param doSomethingCode 功能代码 只能为一位
     * @return 返回生成的编号
     */
    public static String getOrderCode(Long userId, Integer doSomethingCode) {

        DatePlus datePlus = new DatePlus();
        String currentTime = datePlus.toString("yyyyMMddHHmmssSSS");
        StringBuffer sb = new StringBuffer();
        StringBuffer append = sb.append(currentTime).append(userId).append(doSomethingCode);
        return append.toString(); //与用户的主键和操作的功能编号拼接
    }

    /**
     * 订单号和流水号生成策略
     *
     * @param userId 用户的主键
     * @return 返回生成的编号
     */
    public static String getOrderCode(Long userId) {

        DatePlus datePlus = new DatePlus();
        String currentTime = datePlus.toString("yyyyMMddHHmmssSSS");
        StringBuffer sb = new StringBuffer();
        StringBuffer append = sb.append(currentTime).append(userId);
        return append.toString(); //与用户的主键和操作的功能编号拼接
    }

    /**
     * 判断页面请求的参数是否为空，为空则状态码为456
     *
     * @param code      结果状态码
     * @param haveError 是否存在错误
     */
    public void sendResult(String code, Boolean haveError) {

        Map<String, Object> map = new LinkedHashMap<>();
        map.put("code", code);
        map.put("haveError", haveError);
        renderJson(map);
    }

    /**
     * 判断页面请求的参数是否为空，为空则状态码为456
     *
     * @param code   结果状态码
     * @param detail 是否存在错误
     */
    public void sendResult(String code, String detail) {

        Map<String, Object> map = new LinkedHashMap<>();
        map.put("code", code);
        map.put("haveError", true);
        map.put("msg", detail);
        renderJson(map);
    }

    /**
     * 判断页面请求的参数是否为空，为空则状态码为456
     *
     * @param jumpPage   需要跳转到的界面
     */
    public void sendResult(String jumpPage) {

        setAttr("code", "456");
        setAttr("haveError", true);
        setAttr("msg", "请求参数为空");
        render(jumpPage);
    }

    /**
     * 按照传入的参数获取properties文件中的对应属性值
     * @param urlName 属性键名称
     * @return 返回获取的对应参数值
     */
    public static String getPaysRetURL(String urlName){
        Prop use = PropKit.use("service/retrurnURL.properties");
        return use.get(urlName);
    }

    /**
     * 判断传入的对象属性是否都为空
     *
     * @param t   需要进行判断的类
     * @return 返回布尔类型
     */
    public static <T> Boolean validate(T t) {
        Boolean flag = false;
        try {
            for (Field f : t.getClass().getDeclaredFields()) {
                f.setAccessible(true);
                if (f.get(t) != null)  //判断字段是否为空，并且对象属性中的基本都会转为对象类型来判断
                {
                    flag = true;
                }
            }
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return flag;
    }

}
